#pragma once

#include "../Meshes/MeshObject.h"
#include "Material.h"

using namespace DirectX;

ref class GameEngine;

ref class GameObject
{
internal:
	enum PulseState
	{
		None,
		Start,
		FadeUp,
		Duration,
		FadeDown
	};

	GameObject();

	void PulseColor(DirectX::XMFLOAT4 color, float fadeUp, float duration, float fadeDown, float colorMaxPercent, float diffuseMinPercent);
	void EndPulse();

	virtual void Update(GameEngine^ gameEngine);

	virtual void Render(
		_In_ ID3D11DeviceContext *context,
		_In_ ID3D11Buffer *primitiveConstantBuffer,
		_In_ bool isFirstPass
		);

	void Mesh(_In_ MeshObject^ mesh);

	void SetMaterial(_In_ Material^ material);
	Material^ GetMaterial();

	void Position(DirectX::XMFLOAT3 position);
	void Position(DirectX::FXMVECTOR position);
	void OldPosition(DirectX::XMFLOAT3 position);
	void OldPosition(DirectX::FXMVECTOR position);

	void Velocity(DirectX::XMFLOAT3 velocity);
	void Velocity(DirectX::FXMVECTOR velocity);
	void Scale(DirectX::XMFLOAT3 scale);
	void Scale(DirectX::FXMVECTOR scale);
	void Rotation(DirectX::XMFLOAT3 rotation);
	void Rotation(DirectX::FXMVECTOR rotation);

	DirectX::XMMATRIX ModelMatrix();
	DirectX::XMFLOAT3 Position();
	DirectX::XMVECTOR VectorPosition();
	DirectX::XMFLOAT3 OldPosition();
	DirectX::XMVECTOR OldVectorPosition();
	DirectX::XMVECTOR VectorVelocity();
	DirectX::XMFLOAT3 Velocity();
	DirectX::XMFLOAT3 Scale();
	DirectX::XMFLOAT3 Rotation();

	void Active(bool active);
	bool Active();

protected private:
	bool                m_active;

	DirectX::XMFLOAT3   m_position;
	DirectX::XMFLOAT3	m_oldPosition;
	DirectX::XMFLOAT3   m_velocity;
	DirectX::XMFLOAT3   m_scale;
	DirectX::XMFLOAT3	m_rotation;
	DirectX::XMFLOAT4X4 m_modelMatrix;


	Material^           m_material;
	DirectX::XMFLOAT3   m_defaultXAxis;
	DirectX::XMFLOAT3   m_defaultYAxis;
	DirectX::XMFLOAT3   m_defaultZAxis;

	MeshObject^         m_mesh;
	GameEngine^			m_gameEngine;

	float				m_pulseTimer;
	float				m_fadeUp, m_duration, m_fadeDown;
	float				m_colorMaxPercent;
	float				m_diffuseMinPercent;
	DirectX::XMFLOAT4   m_colorAndDiffuseOriginalPercents;
	DirectX::XMFLOAT4	m_pulseColor;
	PulseState			m_pulseState;
};

__forceinline void GameObject::Position(DirectX::XMFLOAT3 position)
{
	m_oldPosition = m_position;
	m_position = position;
}

__forceinline void GameObject::Position(DirectX::FXMVECTOR position)
{
	m_oldPosition = m_position;
	XMStoreFloat3(&m_position, position);
}

__forceinline DirectX::XMFLOAT3 GameObject::Position()
{
	return m_position;
}

__forceinline DirectX::XMVECTOR GameObject::VectorPosition()
{
	return DirectX::XMLoadFloat3(&m_position);
}

__forceinline void GameObject::OldPosition(DirectX::XMFLOAT3 position)
{
	m_oldPosition = position;
}

__forceinline void GameObject::OldPosition(DirectX::FXMVECTOR position)
{
	DirectX::XMStoreFloat3(&m_oldPosition, position);
}

__forceinline DirectX::XMFLOAT3 GameObject::OldPosition()
{
	return m_oldPosition;
}

__forceinline DirectX::XMVECTOR GameObject::OldVectorPosition()
{
	return DirectX::XMLoadFloat3(&m_oldPosition);
}

__forceinline void GameObject::Velocity(DirectX::XMFLOAT3 velocity)
{
	m_velocity = velocity;
}

__forceinline void GameObject::Velocity(DirectX::FXMVECTOR velocity)
{
	XMStoreFloat3(&m_velocity, velocity);
}

__forceinline DirectX::XMFLOAT3 GameObject::Velocity()
{
	return m_velocity;
}

__forceinline void GameObject::Scale(DirectX::XMFLOAT3 scale)
{
	m_scale = scale;
}

__forceinline void GameObject::Scale(DirectX::FXMVECTOR scale)
{
	XMStoreFloat3(&m_scale, scale);
}

__forceinline DirectX::XMFLOAT3 GameObject::Scale()
{
	return m_scale;
}

__forceinline DirectX::XMVECTOR GameObject::VectorVelocity()
{
	return DirectX::XMLoadFloat3(&m_velocity);
}

__forceinline void GameObject::SetMaterial(_In_ Material^ material)
{
	m_material = material;
}

__forceinline Material^ GameObject::GetMaterial()
{
	return m_material;
}

__forceinline void GameObject::Mesh(_In_ MeshObject^ mesh)
{
	m_mesh = mesh;
}

__forceinline DirectX::XMMATRIX GameObject::ModelMatrix()
{
	return DirectX::XMLoadFloat4x4(&m_modelMatrix);
}

__forceinline void GameObject::Active(bool active)
{
	m_active = active;
}

__forceinline bool GameObject::Active()
{
	return m_active;
}

__forceinline void GameObject::Rotation(DirectX::XMFLOAT3 rotation)
{
	m_rotation = rotation;
}

__forceinline void GameObject::Rotation(DirectX::FXMVECTOR rotation)
{
	XMStoreFloat3(&m_rotation, rotation);
}

__forceinline DirectX::XMFLOAT3 GameObject::Rotation()
{
	return m_rotation;
}
